package dashboard.db;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.bj58.sfft.utility.dao.basedao.ConnectionHelper;
import com.bj58.sfft.utility.dao.basedao.DAOHelper;
import com.bj58.sfft.utility.dao.basedao.IDAO;
import com.bj58.sfft.utility.dao.statementcreater.IStatementCreater;
import com.bj58.sfft.utility.dao.util.Common;
import com.bj58.sfft.utility.dao.util.PropertiesHelper;

/**
 * 重写架构部的 DAOBase 不替换关键字，没有防SQL注入功能
 * @author zhaoxiang 20150202
 *
 */
public abstract class MyDAOBase
	    implements IDAO
	{

	    protected MyDAOBase()
	    {
	        qurryTimeOut = 2;
	        insertUpdateTimeOut = 5;
	        printlnSqlAndTime = false;
	    }

	    public static DAOHelper createIntrance()
	        throws Exception
	    {
	        return createDAO("db.properties");
	    }

	    public static DAOHelper createIntrance(String configPath)
	        throws Exception
	    {
	        return createDAO(configPath);
	    }

	    private static DAOHelper createDAO(String configPath)
	        throws Exception
	    {
	        ConnectionHelper ch = new ConnectionHelper(configPath);
	        PropertiesHelper ph = new PropertiesHelper(configPath);
	        DAOHelper dao = new DAOHelper(ch);
	        MyDAOBase sqlDAO = null;
	        String sqlCreaterClass = ph.getString("SqlCreaterClass");
	        if(sqlCreaterClass != null && !sqlCreaterClass.equalsIgnoreCase(""))
	        {
	            if(sqlCreaterClass.equalsIgnoreCase("com.bj58.sfft.utility.dao.sqlcreate.SqlServerSQLCreater"))
	                sqlCreaterClass = "com.bj58.sfft.utility.dao.statementcreater.SqlServerPSCreater";
	            if(sqlCreaterClass.equalsIgnoreCase("com.bj58.sfft.utility.dao.sqlcreate.MySqlSQLCreater"))
	                sqlCreaterClass = "com.bj58.sfft.utility.dao.statementcreater.MysqlPSCreater";
	            logger.info((new StringBuilder("init SqlCreaterClass:")).append(sqlCreaterClass).toString());
	            IStatementCreater creater = (IStatementCreater)Class.forName(sqlCreaterClass).newInstance();
	            sqlDAO = new MyDAOHandler(creater);
	            sqlDAO.connHelper = ch;
	            sqlDAO.qurryTimeOut = ph.getInt("QurryTimeOut");
	            sqlDAO.insertUpdateTimeOut = ph.getInt("InsertUpdateTimeOut");
	            sqlDAO.printlnSqlAndTime = ph.getBoolean("PrintlnSqlAndTime");
	        }
	        MyDAOBase procDAO = null;
	        String procCreaterClass = ph.getString("ProcCreaterClass");
	        if(procCreaterClass != null && !procCreaterClass.equalsIgnoreCase(""))
	        {
	            if(procCreaterClass.equalsIgnoreCase("com.bj58.sfft.utility.dao.sqlcreate.BJ58AutoCreateProcParaCreater"))
	                procCreaterClass = "com.bj58.sfft.utility.dao.statementcreater.BJ58ProcCSCreater";
	            logger.info((new StringBuilder("init ProcCreaterClass:")).append(procCreaterClass).toString());
	            IStatementCreater creater = (IStatementCreater)Class.forName(procCreaterClass).newInstance();
	            procDAO = new MyDAOHandler(creater);
	            procDAO.connHelper = ch;
	            procDAO.qurryTimeOut = ph.getInt("QurryTimeOut");
	            procDAO.insertUpdateTimeOut = ph.getInt("InsertUpdateTimeOut");
	        }
	        dao.sql = sqlDAO;
	        dao.proc = procDAO;
	        logger.info("create DAOHelper success!");
	        return dao;
	    }

	    @SuppressWarnings("rawtypes")
		protected <T> List<T> populateData(ResultSet resultSet, Class<T> clazz)
	        throws Exception
	    {
	        List<T> dataList = new ArrayList<T>();
	        List<Field> fieldList = Common.getAllFields(clazz);
	        ResultSetMetaData rsmd = resultSet.getMetaData();
	        int columnsCount = rsmd.getColumnCount();
	        List<String> columnNameList = new ArrayList<String>();
	        for(int i = 0; i < columnsCount; i++)
	            columnNameList.add(rsmd.getColumnLabel(i + 1).toLowerCase());

	        T bean;
	        for(; resultSet.next(); dataList.add(bean))
	        {
	            bean = clazz.newInstance();
	            for(Iterator<Field> iterator = fieldList.iterator(); iterator.hasNext();)
	            {
	                Field f = (Field)iterator.next();
	                String columnName = Common.getDBCloumnName(clazz, f).toLowerCase();
	                if(columnNameList.contains(columnName))
	                {
	                    Object columnValueObj = null;
	                    Class filedCls = f.getType();
	                    if(filedCls == Integer.TYPE || filedCls == java.lang.Integer.class)
	                        columnValueObj = Integer.valueOf(resultSet.getInt(columnName));
	                    else
	                    if(filedCls == java.lang.String.class)
	                        columnValueObj = resultSet.getString(columnName);
	                    else
	                    if(filedCls == Boolean.TYPE || filedCls == java.lang.Boolean.class)
	                        columnValueObj = Boolean.valueOf(resultSet.getBoolean(columnName));
	                    else
	                    if(filedCls == Byte.TYPE || filedCls == java.lang.Byte.class)
	                        columnValueObj = Byte.valueOf(resultSet.getByte(columnName));
	                    else
	                    if(filedCls == Short.TYPE || filedCls == java.lang.Short.class)
	                        columnValueObj = Short.valueOf(resultSet.getShort(columnName));
	                    else
	                    if(filedCls == Long.TYPE || filedCls == java.lang.Long.class)
	                        columnValueObj = Long.valueOf(resultSet.getLong(columnName));
	                    else
	                    if(filedCls == Float.TYPE || filedCls == java.lang.Float.class)
	                        columnValueObj = Float.valueOf(resultSet.getFloat(columnName));
	                    else
	                    if(filedCls == Double.TYPE || filedCls == java.lang.Double.class)
	                        columnValueObj = Double.valueOf(resultSet.getDouble(columnName));
	                    else
	                    if(filedCls == java.math.BigDecimal.class)
	                        columnValueObj = resultSet.getBigDecimal(columnName);
	                    else
	                        columnValueObj = resultSet.getObject(columnName);
	                    if(columnValueObj != null)
	                    {
	                        Method setterMethod = Common.getSetterMethod(clazz, f);
	                        setterMethod.invoke(bean, new Object[] {
	                            columnValueObj
	                        });
	                    }
	                }
	            }

	        }

	        return dataList;
	    }

	    public void printlnSqlAndTime(String sql, long stime)
	    {
	        if(printlnSqlAndTime)
	            logger.info((new StringBuilder("Execute Sql: ")).append(sql).append(" Time: ").append(System.currentTimeMillis() - stime).append(" ms").toString());
	    }

	    protected IStatementCreater psCreater;
	    protected ConnectionHelper connHelper;
	    protected int qurryTimeOut;
	    protected int insertUpdateTimeOut;
	    protected boolean printlnSqlAndTime;
	    @SuppressWarnings("unused")
		private static final String DB_CONFIG_PATH = "db.properties";
	    protected static final Log logger = LogFactory.getLog(MyDAOBase.class);

	}
